package org.kitrum.example.spring.context;

import com.sun.org.apache.xpath.internal.objects.XString;
import org.kitrum.example.model.UserBean;
import org.kitrum.example.spring.factory.UserFactoryBean;
import org.kitrum.example.spring.factory.UserObjectFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.core.ResolvableType;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: kitrum-example
 * @description:
 * @author: Kun
 * @create: 2021-01-22 17:02
 */
public class ContextApplication {
    public static void abstractBeanFactory()
    {

    }
    /**
     *
     */
    public static void defaultSingletonBeanRegister()
    {
        DefaultSingletonBeanRegistry registry = new DefaultSingletonBeanRegistry();
        registry.registerSingleton("user",new UserBean());
        registry.getSingleton("user_1",new UserObjectFactory());
        UserBean userBean = (UserBean) registry.getSingleton("user");
        UserBean userBean_2 = (UserBean) registry.getSingleton("user_1");
        userBean_2.print();
        userBean.print();
        System.out.println(userBean.equals(userBean_2));
        Set<String> set = new HashSet<>();
        System.out.println(set.add("a"));
        System.out.println(set.add("a"));
        //添加bean的依赖
        registry.registerContainedBean("userService","roleService");
        System.out.println(Arrays.toString(registry.getDependentBeans("userService")));
    }

    /**
     * 继承ListableBeanFactory接口的简单实现，
     * 只是将对象简单的存储在一个{@link java.util.LinkedHashMap}中，
     * 实现在Bean的添加和获取，并支持FactoryBean，如果获取的是FactoryBean则去调用getObject方法
     * @see org.springframework.beans.factory.support.StaticListableBeanFactory
     */
    public static void staticListableBeanFactory()
    {
        StaticListableBeanFactory beanFactory = new StaticListableBeanFactory();
//        staticListableBeanFactory.addBean("user",new UserBean());
        beanFactory.addBean("userFactoryBean",new UserFactoryBean());
        //处理Bean name，如果是工厂名带有“&”前缀的则去掉前缀
        //从Bean缓存中获取Bean
        //如果不存在抛出找不到Bean的错误信息
        //判断name是否为工厂Bean 的名字并且判断类型是否为FactoryBean
        //如果获得的Bean是工厂Bean，如果是以“&”开头的则返回FactoryBean的实例，如果不是则调用FactoryBean.getObject()方法
        try {
            //通过普通的BeanName获取Bean对象
            // Object getBean(String name)
            UserFactoryBean userFactoryBean = (UserFactoryBean) beanFactory.getBean("&userFactoryBean");
            UserBean userBean3 =  userFactoryBean.getObject();
//            userBean3.print();
            UserBean  userBean = (UserBean) beanFactory.getBean("userFactoryBean");
            UserBean  userBean2 = (UserBean) beanFactory.getBean("userFactoryBean");
//            userBean.print();
//            System.out.println(userBean.equals(userBean2));
//            System.out.println(userBean.equals(userBean3));
            //通过类返回Bean对象
            //<T> T getBean(String name, @Nullable Class<T> requiredType)
            UserBean  userBean_3 = beanFactory.getBean(UserBean.class);
            userBean_3.print();
            //通过扫描注解的方式获取bean
            Map<String, Object> beanMap = beanFactory.getBeansWithAnnotation(Resource.class);
            System.out.println(beanMap.size());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
//        staticListableBeanFactory();
        defaultSingletonBeanRegister();
    }
}
